/**
 * @brief Multiplexor Win32 version by select. 
 */
#ifndef HERM_SOCKET_SELECT_MULTIPLEXOR_IMPL_H
#define HERM_SOCKET_SELECT_MULTIPLEXOR_IMPL_H

#pragma warning(disable:4251)
#include "herm/export_symbols.h"
#include "herm/base/socket/socket_def.h"

class SockMgr;
namespace herm{

struct ISockHandler;
class HERM_API Multiplexor
{
public:
	Multiplexor(int size, int timeout = -1, bool lt = true);
	~Multiplexor();

	void Run();
	void Register(ISockHandler* eh, MultiplexorMask mask);
	void Remove(ISockHandler* eh);
	void EnableMask(ISockHandler* eh, MultiplexorMask mask);
	void DisableMask(ISockHandler* eh, MultiplexorMask mask);
private:
    herm::Handle GetSets(fd_set* &rfds, fd_set* &wfds, fd_set* &efds);
	inline void GetSet(bool fdsFlag, fd_set& in, fd_set* &out)
	{
		if (fdsFlag)
			out = &in;
        else
            out = nullptr;
	}

	/**
	 * @brief Handle sockets of removed by other thread.\n
	 *       1) Logic thread, invoke Remove() to removed one fd;
	 *       2) Multiplexor thread, after select returning, handle removed fds at first,\n
	 *          two step: 
	 *          1) Erase the handler object of mapping fd.
	 *          2) handler->Error(ST_REMOVED) to notify logic thread can delete handler.
	 */
	void HandleRemovedFds();
	void DispatchEvent(const fd_set* rfds, const fd_set* wfds, const fd_set* efds);
	void DispatchEvent(const fd_set* fds, MultiplexorMask mask);
private:
    timeval m_timeout;
	SockMgr* m_sockMgr;
	fd_set m_rfds;
	fd_set m_wfds;
	fd_set m_efds;
};
} // end namespace herm{

#endif

